﻿using Framework.Utils;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Text;
using System.Web;

namespace Framework.Components
{
    /// <summary>
    /// 配置接口对象
    /// </summary>
    public interface IConfig
    {
        /// <summary>
        /// 获取配置参数
        /// </summary>
        T Get<T>(string key, T defaultValue = default(T));
    }

    /// <summary>
    /// 缓存配置, 基类
    /// </summary>
    public abstract class CacheConfig : IConfig
    {
        /// <summary>
        /// 配置缓存
        /// </summary>
        private Dictionary<string, object> temps;

        public CacheConfig()
        {
            temps = new Dictionary<string, object>();
        }

        /// <summary>
        /// 获取配置
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T Get<T>(string key, T defaultValue = default(T))
        {
            // 从缓存获取
            if (temps.ContainsKey(key)) { return (T)temps[key]; }
            // 从数据获取
            T obj = GetNew<T>(key);
            if (obj == null) { return defaultValue; }
            temps[key] = obj;
            return obj;
        }

        /// <summary>
        /// 首次获取配置
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        protected abstract T GetNew<T>(string key);
    }

    /// <summary>
    /// 配置对象
    /// </summary>
    public class Config : IConfig
    {
        protected Dictionary<string, string> condigs;

        public Config() : this(new Dictionary<string, string>()) { }

        public Config(Dictionary<string, string> condigs)
        {
            this.condigs = condigs;
        }

        public T Get<T>(string key, T defaultValue = default(T))
        {
            if (!condigs.ContainsKey(key)) { return defaultValue; }
            // 获取数据
            string value = condigs[key];
            if (value == null) { return defaultValue; }
            return Utils.Utils.ToValue<T>(value);
        }
    }

    /// <summary>
    /// 文件配置
    /// </summary>
    public class FileConfig : Config
    {
        /// <summary>
        /// 读取配置
        /// </summary>
        public FileConfig(string path)
        {
            Load(path);
        }

        /// <summary>
        /// 加载配置, 格式: 逐行key=value
        /// </summary>
        protected virtual void Load(string path)
        {
            // 判断文件
            var fullPath = Path.GetFullPath(path);
            if (!File.Exists(fullPath))
            {
                return;
            }

            // 读取内容
            StreamReader sr = null;
            try
            {
                sr = new StreamReader(fullPath);
                // 读取配置
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    // Log.Info("xml template:" + line);
                    var sstrs = line.Split('=');
                    if(sstrs==null || sstrs.Length < 2) { continue; }
                    condigs[sstrs[0]] = HttpUtility.UrlDecode(sstrs[1]);
                }
            }
            catch (Exception e)
            {
                Log.Error("读取文件错误! " + fullPath, e);
            }
            finally
            {
                if (sr != null)
                {
                    sr.Close();
                    sr = null;
                }
            }
        }

    }

    /// <summary>
    /// 读写配置
    /// </summary>
    public class WriteFileConfig: FileConfig
    {
        protected string path;

        public WriteFileConfig() : this(GetAppTempFile())
        {
        }

        public WriteFileConfig(string path) : base(path)
        {
            this.path = path;
        }

        /// <summary>
        /// 设置参数
        /// </summary>
        public void Set(string key, string value)
        {
            condigs[key] = value;
            Save();
        }

        /// <summary>
        /// 保存配置
        /// </summary>
        public void Save()
        {
            var strBdr = new StringBuilder();
            foreach(string key in condigs.Keys)
            {
                var value = condigs[key];
                strBdr.Append(key).Append("=").Append(HttpUtility.UrlEncode(value)).Append("\r\n");
            }
            FileUtils.SaveFile(path, strBdr.ToString(), "UTF-8");
        }

        /// <summary>
        /// 获取临时配置文件路径
        /// </summary>
        public static string GetAppTempFile()
        {
            return GetAppTempPath() + Path.DirectorySeparatorChar + "user.ini";
        }

        /// <summary>
        /// 获取引用配置临时路径
        /// </summary>
        public static string GetAppTempPath()
        {
            string temp = System.Environment.GetEnvironmentVariable("TEMP");
            if (string.IsNullOrEmpty(temp))
            {
                return AppDomain.CurrentDomain.BaseDirectory; //启动程序路径;
            }
            return temp;
        }

    }

#if NETCOREAPP2_0 || NETCOREAPP1_0 || NETCOREAPP1_1
    // .net core 代码
#else
    /// <summary>
    /// 使用系统App配置
    /// </summary>
    public class AppConfig : IConfig
    {
#if DEBUG
        protected const string ConfigFilePath = "configFilePathDebug";
#else
        protected const string ConfigFilePath = "configFilePath";
#endif
        protected Configuration config;

        public AppConfig()
        {
            Load(Get<string>(ConfigFilePath));
        }

        /// <summary>
        /// 读取配置
        /// </summary>
        /// <param name="path"></param>
        public AppConfig(string path)
        {
            Load(path);
        }

        /// <summary>
        /// 加载配置
        /// </summary>
        /// <param name="path"></param>
        protected virtual void Load(string path)
        {
            if (path == null || path.Length <= 0) { return; }
            // 检测文件是否存在
            if (!File.Exists(path))
            {
                throw new Exception("配置文件不存在! filepath=" + path + " current=" + Environment.CurrentDirectory + " basedir=" + AppDomain.CurrentDomain.BaseDirectory);
            }

            // 读取配置
            ExeConfigurationFileMap map = new ExeConfigurationFileMap();
            map.ExeConfigFilename = path;
            config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
            if (config == null)
            {
                throw new Exception("无法读取配置! " + path);
            }

            // string value = config.AppSettings.Settings["debug"].Value;
        }

        public T Get<T>(string key, T defaultValue = default(T))
        {
            return GetByConfiguration<T>(key, defaultValue);
        }

        /// <summary>
        /// 从ConfigurationManager获取参数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        protected T GetByConfiguration<T>(string key, T defaultValue)
        {
            // 尝试通过配置获取
            string value = null;
            if (config != null)
            {
                var keyValue = config.AppSettings.Settings[key];
                value = (keyValue != null) ? keyValue.Value : null;
            }
            // 通过默认配置获取
            if (value == null)
            {
                value = ConfigurationManager.AppSettings[key];
            }
            // 空过滤
            if (value == null) { return defaultValue; }
            return Utils.Utils.ToValue<T>(value);
        }


        /// <summary>
        /// 读取ConnectionStrings配置
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public ConnectionStringSettings GetConnectionStrings(string key)
        {
            // 通过自定义配置获取
            if (config != null)
            {
                return config.ConnectionStrings.ConnectionStrings[key];
            }
            // 通过默认配置获取
            return ConfigurationManager.ConnectionStrings[key];
        }


    }
#endif



}
